package org.hawk.gwt.ppc.javacc;

import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;

import org.hawk.gwt.ppc.scanner.Processor;
import org.hawk.gwt.ppc.scanner.Token;
import org.hawk.gwt.ppc.scanner.TokenChain;

import junit.framework.TestCase;

public class JavaStreamTestCase extends TestCase {
	private static final String MOCK01 = "./src/org/hawk/gwt/ppc/javacc/mock/Mock.java";

	public void testMockBase() throws ParseException, IOException{
		StringWriter stream = new StringWriter();
		JavaScanner scanner = new JavaScanner();
		scanner.startScan(new FileReader(MOCK01),stream);
		assertEquals(getMockString(MOCK01), stream.toString());
	}
	
	public void testAddModify() throws ParseException, IOException {
		StringWriter stream = new StringWriter();
		JavaScanner scanner = new JavaScanner();
		scanner.addProcessor(JavaParserTreeConstants.JJTCOMPILATIONUNIT,new TestProcessor());
		scanner.startScan(new FileReader(MOCK01),stream);
		assertEquals(getMockString(MOCK01)+"/**/", stream.toString());
	}
	
	public void testMockModify() throws ParseException, IOException {
		StringWriter stream = new StringWriter();
		JavaScanner scanner = new JavaScanner();
		//scanner.addProcessor(JavaParserTreeConstants.JJTNAME,new TestProcessorModifier());
		scanner.addProcessor(JavaParserTreeConstants.JJTPRIMARYSUFFIX,new TestProcessorModifier());
		scanner.startScan(new FileReader(MOCK01),stream);
		assertEquals(getMockString(MOCK01)
			.replaceFirst("getClass", "getClsDelegate")
			.replaceFirst("getClass", "getClsDelegate"),
			stream.toString());
	}

	private String getMockString(String location) throws IOException {
		StringWriter stream = new StringWriter();
		
		FileReader reader = null;
		try {
			reader = new FileReader(location);
			
			int len = 0;
			char[] buf = new char[1024];
			while((len = reader.read(buf))>0){
				stream.write(buf,0,len);
			}
		} finally {
			reader.close();
		}
		return stream.toString();
	}
	
	private static class TestProcessor implements Processor{

		public void visitStart(TokenChain<? extends Token> iterator,int kind) {}

		public void visitEnd(TokenChain<? extends Token> iterator,int kind) {
			iterator.add("/**/");
		}
		
	}
	
	private static class TestProcessorModifier implements Processor{

		public void visitStart(TokenChain<? extends Token> iterator,int kind) {}

		public void visitEnd(TokenChain<? extends Token> iterator,int kind) {
			Token tok = iterator.previous();
			if(tok.getToken().equals("getClass")){
				String raw = tok.getRawToken();
				tok.setToken(raw.replace("getClass", "getClsDelegate"));
			}
		}
		
	}
}
